#pragma once
#include <game/Config.h>
#include <game/Service.h>

#include <system/assert.h>
#include <memory>
#include <map>
#include <iterator>

ARELLO_GAME_NAMESPACE_DECL_START

class ServiceProvider
{
public:
	template<typename T>
	void Register(std::auto_ptr<T> service)
	{
		this->ownedServices.insert(
			std::make_pair(T::Magic(), service.release()));
	}

	template<typename T>
	T* Query()
	{
		std::map<int, ServiceBase*>::iterator i =
			this->ownedServices.find(T::Magic());

		if (i == this->ownedServices.end())
		{
			LIBA_FAIL("Couldn't find requested service");
			return 0;
		}

		return static_cast<T*>(i->second);	
	}

	void MergeFrom(ServiceProvider& rhs)
	{
		std::copy(rhs.ownedServices.begin(), rhs.ownedServices.end(),
			std::inserter(this->ownedServices, this->ownedServices.begin()));

		rhs.ownedServices.clear();
	}
protected:
	~ServiceProvider()
	{
		for (std::map<int, ServiceBase*>::iterator i = ownedServices.begin();
			i != ownedServices.end(); ++i)
		{
			delete i->second;
		}
	}
private:
	std::map<int, ServiceBase*> ownedServices;
	friend class GameDefinition;
};

ARELLO_GAME_NAMESPACE_DECL_END